﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;


namespace ConsoleApplication3
{
    class Program
    {
        static void Main(string[] args)
        {
            Introdusing();
            MainManu();
            ReplayMainManu();
            Console.ReadLine();
        }

        static string Introdusing()
        {
            string name = GetUserName();
            SayHello(name);
            return name;

        }

        static void ReplayMainManu()
        {
            Console.ReadLine();
            Console.Clear();
            Console.WriteLine("Eсли хотите повторить опыт, нажмите 1, если же нет, введите любую другую цифру");
            
            int a = ReadIntFromConsole();
            if (a == 1)
            {

                MainManu();
                ReplayMainManu();
            }
            else
                Console.WriteLine("Пакеда;)");



        }
        static void MainManu()
        {
            Console.WriteLine(" Какую сортировку ты хочешь выбрать?");
            Console.WriteLine("1) Сортировка выбором.");
            Console.WriteLine("2) Сортировка пузырьком.");
            Console.WriteLine("3) Гномья сортировка.");
         
            SortType sortType = (SortType)ReadIntFromConsoleMaxMinValues(1,4);
            Console.Clear();

            if (sortType == SortType.Selection)
            {
                Console.WriteLine("Вы выбрали сортировку выбором");

            }
             if (sortType == SortType.Bubble)
            {
                Console.WriteLine("Вы выбрали сортировку пузырьком");
            }
              if (sortType == SortType.Ghnome)
            {
                Console.WriteLine("Вы выбрали  гномью сортировку ");
            }
      

            int arrayLenght = LengthArray();
            int typeArray = SelectedTypeArray();

            Console.Clear();

             switch (typeArray)
            {

                case 1:
                    if (typeArray == 1)

                       
                        Console.WriteLine("Вы выбрали для создания отсортированый массив");
                    int[] array = CreateSortedArray(arrayLenght);
                    PrintArray(array);
                    Console.ReadKey();
                    int min = array[0];
                    int max = array[arrayLenght - 1];
                    switch (sortType)
                 
                    {
                        case SortType.Selection:
                            SelectionSort(array);
                            break;

                        case SortType.Bubble:
                            BubbleSort(array,min,max);
                            break;

                        case SortType.Ghnome:
                            GnomeSort(array);
                            break;

                    }

                    Console.WriteLine("Отсортированный массив:");

                    PrintArray(array);


                    break;
                case 2:
                    if (typeArray == 2)

                        Console.WriteLine("Вы выбрали для создания случайный массив");

                    int[] randomArray = CreateRandomArray(arrayLenght, 0, 100);
                    PrintArray(randomArray);
                    Console.ReadKey();
                    int min1 = randomArray[0];
                    int max1 = randomArray[arrayLenght - 1];
                
                 switch (sortType)
                    {
                        case SortType.Selection:
                           SelectionSort(randomArray);
                           break;

                        case SortType.Bubble:
                           BubbleSort(randomArray,min1,max1);
                           break;

                        case SortType.Ghnome:
                           GnomeSort(randomArray);
                           break;
                    }
                   
                    Console.WriteLine("Отсортированный массив:");
                    PrintArray(randomArray);
                    Console.ReadKey();
                     
                     /* Console.WriteLine("Желаете ли вы посмотреть процесс сортирвки: <y/n>?");
            bool draw = AskToDraw();
            if (!draw)
            {
                Console.Clear();
                ChooseArrayTypeForDrawing(sortType , randomArray);
           

                // вызов отрисовки

            }*/
                     break;

                case 3:
                    if (typeArray == 3)

                        Console.WriteLine("Вы выбрали для создания реверсный массив");
                   
                    int[] reverseArray = ReverseArray(arrayLenght);
                    int min2 = reverseArray[0];
                    int max2 = reverseArray[arrayLenght - 1];
                    PrintArray(reverseArray);
               
                    switch (sortType)
                  
                    {
                        case SortType.Selection:
                            SelectionSort(reverseArray);
                            break;

                        case SortType.Bubble:
                           BubbleSort(reverseArray,min2,max2);
                           break;

                        case SortType.Ghnome:
                            GnomeSort(reverseArray);
                            break;

                    }
                    Console.WriteLine("Отсортированный массив:");
                    PrintArray(reverseArray);
                    break;


            }
            









        }





        static int LengthArray()
        {
            Console.WriteLine("Введите длинну массива");
            int c = ReadIntFromConsole();
            Console.Clear();

            Console.WriteLine("Вы выбрали массив длинной {0}", c);
            return c;

        }




        static int SelectedTypeArray()
        {
            Console.WriteLine("Выберете тип создаваеммого массива:");
            Console.WriteLine("1) Отсортированный массив.");
            Console.WriteLine("2) Случайный массив.");
            Console.WriteLine("3) Реверсный массив.");
            int selectType = ReadIntFromConsoleMaxMinValues(1, 4);
            return selectType;
        }

        static void TimeSorting()
        {
            Console.WriteLine("Время сортировки массива составило");

        }

        static void PrintSorting()
        {

        }















        //TimeSpan 
        static int ReadIntFromConsole()
        {
            {
                int a = 0;
                bool inputsuccess = false;
                while (!inputsuccess)
                {
                    try
                    {

                        Console.WriteLine("");
                        string number = Console.ReadLine();
                        a = Int32.Parse(number);
                        inputsuccess = true;
                    }
                    catch
                    {
                        Console.WriteLine("Вы ввели некоректное значение");


                    }


                }
                return a;
            }
        }
        static int ReadIntFromConsoleMaxMinValues(int min, int max)
        {
            int result = ReadIntFromConsole();
            while (true)
            {

                if (result >= min && result < max)
                    return result;

                else
                    Console.WriteLine("Выберете один из допустимых массивов");
                result = ReadIntFromConsole();
            }

        }
        static int[] CreateRandomArray(int lenght, int min, int max)
        {
            int[] array = new int[lenght];
            Random r = new Random();
            for (int i = 0; i < array.Length; i++)
            {
                array[i] = r.Next(min, max);

            }
           
            return array;


        }
        static void PrintArray(int[] array)
        {
            for (int i = 0; i < array.Length; i++)
            {
                Console.Write("{0} |", array[i]);
            }
        }
        static int[] CreateSortedArray(int arrayLenght)
        {


            int[] result = new int[arrayLenght];
            for (int i = 0; i < result.Length; i++)
            {
                result[i] = i;

            }

            return result;
        }

        static int[] ReverseArray(int arrayLenght)
        {

            int[] array = CreateSortedArray(arrayLenght);
            int[] reverseArray = Reverse(array, arrayLenght);

            PrintArray(reverseArray);
            Console.ReadKey();
            return reverseArray;
        }
        static int[] Reverse(int[] array, int n)
        {

            int i;
            int j;
            int t;
            for (i = 0, j = n - 1; i < j; i++, j--)
            {
                t = array[i];
                array[i] = array[j];
                array[j] = t;
            }

            return array;



        }

        static int[] BubbleSort(int[] A, int min, int max)
        {

            DateTime a = DateTime.Now;
            int temp;

            for (int i = 0; i < A.Length - 1; i++)
            {
                for (int j = 0; j < A.Length - i - 1; j++)
                {
                    if (A[j] > A[j + 1])
                    {
                        temp = A[j];
                        A[j] = A[j + 1];
                        A[j + 1] = temp;
                        Console.Clear();
                        DrawArrayMOD(A, min, max);
                        Thread.Sleep(2);
                    }


                }
                DrawArrayMOD(A, min, max);
                Thread.Sleep(2);
            }
            TimeSpan time = DateTime.Now - a;
            Console.Clear();
            Console.WriteLine("Время сортировки составило:  {0} милисекунд", time.TotalMilliseconds);

            return A;
        }



        static void SelectionSort(int[] arr)
        {

            DateTime a = DateTime.Now;
            int min, temp;
            int length = arr.Length;

            for (int i = 0; i < length - 1; i++)
            {
                min = i;

                for (int j = i + 1; j < length; j++)
                {
                    if (arr[j] < arr[min])
                    {
                        min = j;
                    }
                }

                temp = arr[i];
                arr[i] = arr[min];
                arr[min] = temp;


            }
            TimeSpan time = DateTime.Now - a;
            Console.Clear();
            Console.WriteLine("Время сортировки составило:  {0} милисекунд", time.TotalMilliseconds);

        }

        static void GnomeSort(int[] array)
        {
            DateTime a = DateTime.Now;
            for (int i = 1, temp_value; i < array.Length; )
            {
                if (array[i - 1] <= array[i])
                    i += 1;
                else
                {
                    temp_value = array[i - 1];
                    array[i - 1] = array[i];
                    array[i] = temp_value;
                    i -= 1;
                    if (i == 0)
                        i = 1;

                }
            }

            TimeSpan time = DateTime.Now - a;
            Console.Clear();
            Console.WriteLine("Время сортировки составило:  {0} милисекунд", time.TotalMilliseconds);

        }


        static void sorting(int[] arr, int first, int last) //обращение к методу
        {
            int p = arr[(last - first) / 2 + first];
            int temp;
            int i = first, j = last;
            while (i <= j)
            {
                while (arr[i] < p && i <= last) ++i;
                while (arr[j] > p && j >= first) --j;
                if (i <= j)
                {
                    temp = arr[i];
                    arr[i] = arr[j];
                    arr[j] = temp;
                    ++i; --j;
                }
            }
            if (j > first) sorting(arr, first, j);
            if (i < last) sorting(arr, i, last);
        }
        static string print(int[] array)
        {
            string result = string.Empty;

            int lim = array.Max(), min = array.Min();
            for (int i = min; i <= lim; i++)
            {
                int tmp = 0;
                for (int j = 0; j < array.Length; j++)
                {
                    if (array[j] <= i)
                    {
                        result += "&#9608;";
                        tmp = array[j];
                    }
                    else result += " ";
                }
                result += string.Format(" : {0}\n", tmp);
            }

            return result;
        }
        static string GetUserName()
        {
            Console.WriteLine("Введите имя");
            string userName = Console.ReadLine();
            return userName;

        }
        static void SayHello(string userName)
        {
            Console.WriteLine("Привет {0}! ", userName);
        }

        static int[] QuickSort(int[] a, int i, int j)
        {
            if (i < j)
            {
                int q = Partition(a, i, j);
                a = QuickSort(a, i, q);
                a = QuickSort(a, q + 1, j);
            }
            return a;
        }

      static int Partition(int[] a, int p, int r)
        {
            int x = a[p];
            int i = p - 1;
            int j = r + 1;
            while (true)
            {
                do
                {
                    j--;
                }
                while (a[j] > x);
                do
                {
                    i++;
                }
                while (a[i] < x);
                if (i < j)
                {
                    int tmp = a[i];
                    a[i] = a[j];
                    a[j] = tmp;
                }
                else
                {
                    return j;
                }
            }
        }

      public static void DrawArrayMOD(int[] locArray, int MIN, int MAX)
      {
          int yMin = MIN;
          int yMax = MAX;
          int xMax = locArray.Length;
          int j = 0;
          for (int i = 0; i <= yMax; i++)
          {
              if (locArray[j] == i)
              {
                  Console.SetCursorPosition(j, yMax - locArray[j]);
                  Console.Write(".");
                  j++;
                  i = 0;
              }
              if (j == locArray.Length)
                  break;
          }
      }


        public enum SortType
        {
            Selection,
            Bubble,
            Ghnome,
        }
        public static bool AskToDraw()
        {
            bool exitFlag = true;
            char exit = ' ';
            bool inputIsCorrect = false;
            while (!inputIsCorrect)
            {
                try
                {
                    exit = Char.Parse(Console.ReadLine());
                    if (exit == 'y' || exit == 'n')
                        inputIsCorrect = true;
                    else
                        throw new ArgumentException();
                }
                catch
                {
                    Console.WriteLine("Неправильный ввод");
                    Console.WriteLine("Желаете ли вы посмотреть процесс сортирвки: <y/n>?");
                }
            }
            if (exit == 'y')
                exitFlag = false;
            else
                exitFlag = true;
            return exitFlag;
        }
        public static void ChooseArrayTypeForDrawing(SortType sortType, int[] locArray)
        {
            int length = locArray.Length;
            int MAX = locArray[0], MIN = locArray[0];
            for (int i = 0; i < length; i++)
            {
                if (MIN > locArray[i])
                    MIN = locArray[i];
                if (MAX < locArray[i])
                    MAX = locArray[i];
            }
            switch (sortType)
            {
                case SortType.Bubble:
                    Console.SetWindowPosition(0, 0);
                    Console.SetWindowSize(Console.LargestWindowWidth, Console.LargestWindowHeight);

                    BubbleSort(locArray, MIN, MAX);
                    Console.SetCursorPosition(0, MAX);
                    Console.WriteLine("Массив отсортирован, консоль будет очищена через 5 секунд");
                    Thread.Sleep(5000);
                    Console.Clear();
                    break;
              /*  case SortType.Selection:
                    Console.SetWindowPosition(0, 0);
                    Console.SetWindowSize(Console.LargestWindowWidth, Console.LargestWindowHeight);
                    SelectionSort(locArray, MIN, MAX);
                    Console.SetCursorPosition(0, MAX);
                    Console.WriteLine("Массив отсортирован, консоль будет очищена через 5 секунд");
                    Thread.Sleep(5000);
                    Console.Clear();
                    break;
                case SortType.Shell:
                    Console.SetWindowPosition(0, 0);
                    Console.SetWindowSize(Console.LargestWindowWidth, Console.LargestWindowHeight);
                    ShellSort(locArray, MIN, MAX);
                    Console.SetCursorPosition(0, MAX);
                    Console.WriteLine("Массив отсортирован, консоль будет очищена через 5 секунд");
                    Thread.Sleep(5000);
                    Console.Clear();
                    break;
                case SortType.Shayker:
                    Console.SetWindowPosition(0, 0);
                    Console.SetWindowSize(Console.LargestWindowWidth, Console.LargestWindowHeight);
                    ShaykerSort(locArray, MIN, MAX);
                    Console.SetCursorPosition(0, MAX);
                    Console.WriteLine("Массив отсортирован, консоль будет очищена через 5 секунд");
                    Thread.Sleep(5000);
                    Console.Clear();
                    break;*/
            }
        }
    }
}